﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MegaBitProject.Models;
using MegaBitProject.ViewModels;

namespace MegaBitProject.Controllers
{
    [Authorize]
    public class TicTacToeController : Controller
    {
        //
        // GET: /TicTacToe/

        private IGameRepository rep = null;

        public TicTacToeController()
        {
            rep = new GameRepository();
        }

        public TicTacToeController(IGameRepository _rep)
        {
            rep = _rep;
        }

        //Gets the Tic Tac Toe Application (chat access)
        public ActionResult Lobby()
        {
            var model = (from g in rep.getGames
                     where g.ID == 1
                     select g).SingleOrDefault();

            return View(model);
        }

        //Creates an instance of TTT, calls ActionResult Join with g.ID
        public ActionResult Create()
        {
            Game g = new Game();

            g.appID = (from game in rep.getGames
                       where game.ID == 1
                       select game).SingleOrDefault();
            g.maxPlayers = 2;
            g.minPlayers = 2;
            g.time = DateTime.Now;
            g.userID = (from user in rep.getUser
                        where user.UserName == User.Identity.Name
                        select user).SingleOrDefault();

            UpdateModel(g);

            rep.newGame(g);

            return Join(g.ID);
        }

        // Accepts game ID as parameter, joins user game with the ID
        //redirects to ActionResult game with game ID
        public ActionResult Join(int? id)
        {
            if (id != null)
            {
                int nid = Convert.ToInt32(id);
                PlayedGame g = new PlayedGame();

                g.gameID = (from game in rep.getOpenGames
                            where game.ID == nid
                            select game).SingleOrDefault();

                var counter = (from game in rep.getPlayedGames
                               where game.gameID == g.gameID
                               select game).Count();

                if (g.gameID != null && counter < g.gameID.maxPlayers)
                {
                    g.userID = (from user in rep.getUser
                                where user.UserName == User.Identity.Name
                                select user).SingleOrDefault();
                    g.score = 0;

                    g.timeStamp = DateTime.Now;

                    UpdateModel(g);

                    rep.joinGame(g);

                    return RedirectToAction("Game/" + nid);
                }
                else
                {
                    return RedirectToAction("Lobby");
                }
            }
            else
            {
                return RedirectToAction("Lobby");
            }
        }

        // pick an open game by ID if its available,  calls ActionResult Join
        public ActionResult Random()
        {
            PlayedGame g = new PlayedGame();
            g.gameID = (from game in rep.getOpenGames
                        select game).LastOrDefault();

            if (g.gameID != null)
            {
                g.userID = (from user in rep.getUser
                            where user.UserName == User.Identity.Name
                            select user).SingleOrDefault();
                g.score = 0;
                g.timeStamp = DateTime.Now;
                return Join(g.gameID.ID);
            }
                        
            return RedirectToAction("Lobby");
        }

        // Places the user in the game with the games ID as parameter
        public ActionResult Game(int? id)
        {
            
            if (id.HasValue)
            {
                int nid = Convert.ToInt32(id);

                var instance = (from game in rep.getOpenGames
                                where game.ID == nid
                                select game).SingleOrDefault();
            
                if (instance != null)
                {
                    return View(instance);
                }
                else
                {
                    return RedirectToAction("Lobby");
                }
            }
            else
            {
                return RedirectToAction("Lobby");
            }
        }

        //A list of current TTT games returned as a partial view in lobby
        public ActionResult _CurrentGames()
        {
            CurrentGames view = new CurrentGames();

            view.id = new List<int>();
            view.maxPlayers = new List<int>();
            view.name = new List<string>();
            view.numPlayers = new List<int>();
            view.controller = new List<string>();

            var games = (from game in rep.getOpenGames
                         join app in rep.getGames
                         on game.appID equals app
                         where app.ID == 1
                         orderby game.ID descending
                         select game).ToList();

            foreach (var g in games)
            {
                var numP = (from game in rep.getPlayedGames
                            where game.gameID == g
                            select game).Count();

                var maxP = (from game in rep.getOpenGames
                            where game == g
                            select game).SingleOrDefault();

                if (numP < maxP.maxPlayers)
                {
                    view.numPlayers.Add(numP);
                    view.maxPlayers.Add(maxP.maxPlayers);
                    var name = (from game in rep.getGames
                                where game == maxP.appID
                                select game).SingleOrDefault();

                    view.name.Add(name.name);
                    view.id.Add(maxP.ID);
                    view.controller.Add(name.controller);
                }
            }

            return PartialView(view);
        }
    }
}
